package com.mo.tools.number;

import java.math.BigDecimal;

public class DecimalCalc {

    /**
     * add operation
     *
     * @param augend
     * @param addend
     * @return augend + addend
     */
    public static BigDecimal add(Object augend, Object addend) {
        BigDecimal augendBigDecimal = isEmpty(augend) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(augend));
        BigDecimal addendBigDecimal = isEmpty(addend) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(addend));
        return augendBigDecimal.add(addendBigDecimal);
    }

    /**
     * subtract operation
     *
     * @param minuend
     * @param minus
     * @return minuend - minus
     */
    public static BigDecimal subtract(Object minuend, Object minus) {
        BigDecimal minuendBigDecimal = isEmpty(minuend) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(minuend));
        BigDecimal minusBigDecimal = isEmpty(minus) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(minus));
        return minuendBigDecimal.subtract(minusBigDecimal);
    }

    /**
     * multiply operation
     *
     * @param multiplicand
     * @param multiplier
     * @return multiplicand * multiplier
     */
    public static BigDecimal multiply(Object multiplicand, Object multiplier) {
        BigDecimal multiplicandBigDecimal = isEmpty(multiplicand) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(multiplicand));
        BigDecimal multiplierBigDecimal = isEmpty(multiplier) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(multiplier));
        return multiplicandBigDecimal.multiply(multiplierBigDecimal);
    }

    /**
     * divide opperation
     *
     * @param divisor
     * @param dividend
     * @return divisor / dividend
     */
    public static BigDecimal divide(Object divisor, Object dividend) {
        BigDecimal divisorBigDecimal = isEmpty(divisor) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(divisor));
        BigDecimal dividendBigDecimal = isEmpty(dividend) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(dividend));
        if (dividendBigDecimal.compareTo(BigDecimal.ZERO) == 0) {
            throw new RuntimeException("the divisor cannot be zero");
        }
        return divisorBigDecimal.divide(dividendBigDecimal, 20, BigDecimal.ROUND_DOWN);
    }


    /**
     * BigDecimal convert to byte
     *
     * @param bigDecimal
     * @return
     */
    public static byte toByte(BigDecimal bigDecimal) {
        return bigDecimal.byteValue();
    }

    /**
     * BigDecimal convert to short
     *
     * @param bigDecimal
     * @return
     */
    public static short toShort(BigDecimal bigDecimal) {
        return bigDecimal.shortValue();
    }

    /**
     * BigDecimal convert to int
     *
     * @param bigDecimal
     * @return
     */
    public static int toInt(BigDecimal bigDecimal) {
        return bigDecimal.intValue();
    }

    /**
     * BigDecimal convert to long
     *
     * @param bigDecimal
     * @return
     */
    public static long toLong(BigDecimal bigDecimal) {
        return bigDecimal.longValue();
    }

    /**
     * BigDecimal convert to float
     *
     * @param bigDecimal
     * @return
     */
    public static float toFloat(BigDecimal bigDecimal) {
        return bigDecimal.floatValue();
    }

    /**
     * BigDecimal convert to round down float
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static float toRoundDownFloat(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_DOWN).floatValue();
    }

    /**
     * BigDecimal convert to round half down float
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static float toRoundHalfUpFloat(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    /**
     * BigDecimal convert to double
     *
     * @param bigDecimal
     * @return
     */
    public static double toDouble(BigDecimal bigDecimal) {
        return bigDecimal.doubleValue();
    }


    /**
     * BigDecimal convert to round down double
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static double toRoundDownDouble(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_DOWN).doubleValue();
    }

    /**
     * BigDecimal convert to round half down double
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static double toRoundHalfUpDouble(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * BigDecimal convert to String
     *
     * @param bigDecimal
     * @return
     */
    public static String toString(BigDecimal bigDecimal) {
        return bigDecimal.toString();
    }

    /**
     * BigDecimal convert to round down String
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static String toRoundDownString(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_DOWN).toString();
    }

    /**
     * BigDecimal convert to round half down String
     *
     * @param bigDecimal
     * @param decimalPlace
     * @return
     */
    public static String toRoundHalfUpString(BigDecimal bigDecimal, int decimalPlace) {
        return bigDecimal.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * Object convert to BigDecimal
     *
     * @param decimal
     * @return
     */
    public static BigDecimal toBigDecimal(Object decimal) {
        return isEmpty(decimal) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(decimal));
    }

    /**
     * Object convert percent round down String
     *
     * @param decimal
     * @return
     */
    public static String toPercentRoundDownString(Object decimal) {
        BigDecimal bigDecimal = isEmpty(decimal) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(decimal));
        return multiply(bigDecimal, 100).setScale(0, BigDecimal.ROUND_DOWN).toString().concat("%");
    }

    /**
     * Object convert percent round half up String
     *
     * @param decimal
     * @return
     */
    public static String toPercentRoundHalfUpString(Object decimal) {
        BigDecimal bigDecimal = isEmpty(decimal) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(decimal));
        return multiply(bigDecimal, 100).setScale(0, BigDecimal.ROUND_HALF_UP).toString().concat("%");
    }


    /**
     * a eq b, a == b
     *
     * @param a
     * @param b
     * @return
     */
    public static Boolean eq(Object a, Object b) {
        BigDecimal aDecimal = isEmpty(a) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(a));
        BigDecimal bigDecimal = isEmpty(b) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(b));
        return aDecimal.compareTo(bigDecimal) == 0;
    }

    /**
     * a lt b, a < b
     *
     * @param a
     * @param b
     * @return
     */
    public static Boolean lt(Object a, Object b) {
        BigDecimal aDecimal = isEmpty(a) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(a));
        BigDecimal bigDecimal = isEmpty(b) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(b));
        return aDecimal.compareTo(bigDecimal) < 0;
    }

    /**
     * a lt b, a < b
     *
     * @param a
     * @param b
     * @return
     */
    public static Boolean gt(Object a, Object b) {
        BigDecimal aDecimal = isEmpty(a) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(a));
        BigDecimal bigDecimal = isEmpty(b) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(b));
        return aDecimal.compareTo(bigDecimal) > 0;
    }

    /**
     * a le b, a <= b
     *
     * @param a
     * @param b
     * @return
     */
    public static Boolean le(Object a, Object b) {
        BigDecimal aDecimal = isEmpty(a) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(a));
        BigDecimal bigDecimal = isEmpty(b) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(b));
        return aDecimal.compareTo(bigDecimal) <= 0;
    }

    /**
     * a ge b, a >= b
     *
     * @param a
     * @param b
     * @return
     */
    public static Boolean ge(Object a, Object b) {
        BigDecimal aDecimal = isEmpty(a) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(a));
        BigDecimal bigDecimal = isEmpty(b) ? BigDecimal.ZERO : new BigDecimal(String.valueOf(b));
        return aDecimal.compareTo(bigDecimal) >= 0;
    }


    public static Boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String) {
            return "".equals(obj);
        }
        return false;
    }

    public static void main(String[] args) {
        BigDecimal subtract = DecimalCalc.add(null, null).add(null).subtract(null);
        System.out.println(subtract);
    }


}
